import { sequelize } from '../../sql/db';
import auth from '../../middlewares/auth';
import Area from '../../sql/module/area/area';
import BlockNumber from '../../sql/module/area/block_number';
import RoomNumber from '../../sql/module/area/room_number';
import { Success, Repeatedly, Forbbidend } from '../../code/http-exception';
import { InfoValidator, ListValidator } from '../../validators/public';
import { AddAreaValidator } from '../../validators/area';
import { Op } from "sequelize";
import User from '../../sql/module/user/user';

Area.hasMany(BlockNumber, {
    as: 'children'
})
BlockNumber.belongsTo(Area, { onDelete: 'CASCADE' });
Area.hasMany(RoomNumber)
RoomNumber.belongsTo(Area, { onDelete: 'CASCADE' });
BlockNumber.hasMany(RoomNumber, {
    as: 'children'
})
RoomNumber.belongsTo(BlockNumber, { onDelete: 'CASCADE' });

const router: Api = new Map()

//添加区域area->block->room前两个没有就创建
router.set('/addArea', [auth('addArea'), async (ctx) => {
    const v = await new AddAreaValidator().validate(ctx)
    const area_name = v.get('body.area_name')
    const block_number = v.get('body.block_number')
    const room_number = v.get('body.room_number')
    const AreaId = ctx.auth.AreaId
    if (AreaId) {
        const area = await Area.findOne({
            where: { id: AreaId }
        })
        if (area?.dataValues.name !== area_name) {
            throw new Forbbidend()
        }
    }
    const [area] = await Area.findOrCreate({
        where: { name: area_name },
        defaults: {
            name: area_name
        }
    })
    const [block] = await BlockNumber.findOrCreate({
        where: { name: block_number, AreaId: area.dataValues.id },
        defaults: {
            name: block_number,
            AreaId: area.dataValues.id
        }
    })
    const [room, created] = await RoomNumber.findOrCreate({
        where: { name: room_number, BlockNumberId: block.dataValues.id },
        defaults: {
            name: room_number,
            BlockNumberId: block.dataValues.id,
            AreaId: area.dataValues.id
        }
    })
    if (created)
        throw new Success(room)
    else
        throw new Repeatedly()
}])

//获取区域列表用于添加房间
router.set('/areas', [auth('addArea'), async (ctx) => {
    const AreaId = ctx.auth.AreaId
    const where: any = {}
    AreaId && (where.id = AreaId)
    const areas = await Area.findAll({ where })
    throw new Success(areas)
}])

//获取楼号列表用于添加房间
router.set('/blockNumbers', [auth('addArea'), async (ctx) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const blockNumber = await BlockNumber.findAll({
        where: { AreaId: id }
    })
    throw new Success(blockNumber)
}])

//获取区域列表
router.set('/areaList', [auth('areaList'), async (ctx) => {
    const v = await new ListValidator().validate(ctx)
    const AreaId = ctx.auth.AreaId
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const area_name = v.get('body.area_name')
    const where: any = {}
    AreaId && (where.id = AreaId)
    area_name && (where.name = { [Op.substring]: area_name })
    const { rows, count } = await Area.findAndCountAll({
        attributes: [['name', 'area_name'], 'id'],
        where,
        limit: limit * 1,
        offset: (page_index - 1) * limit
    })
    throw new Success({ list: rows, total: count })
}])

//获取楼号列表
router.set('/blockList', [auth('areaList'), async (ctx) => {
    const AreaId = ctx.auth.AreaId
    const v = await new ListValidator().validate(ctx)
    const area_name = v.get('body.area_name')
    const block_number = v.get('body.block_number')
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const where: any = {}
    block_number && (where['$BlockNumber.name$'] = { [Op.substring]: block_number })
    area_name && (where['$Area.name$'] = { [Op.substring]: area_name })
    AreaId && (where['$Area.id$'] = AreaId)
    const { rows, count } = await BlockNumber.findAndCountAll({
        attributes: [[sequelize.col('BlockNumber.name'), 'block_number'], [sequelize.col('Area.name'), 'area_name'], [sequelize.col('BlockNumber.id'), 'id']],
        where,
        distinct: true,
        include: Area,
        limit: limit * 1,
        offset: (page_index - 1) * limit
    })
    throw new Success({ list: rows, total: count })
}])

//房间列表
router.set('/roomNumberList', [auth('areaList'), async (ctx) => {
    const AreaId = ctx.auth.AreaId
    const v = await new ListValidator().validate(ctx)
    const area_name = v.get('body.area_name')
    const block_number = v.get('body.block_number')
    const room_number = v.get('body.room_number')
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const where: any = {}
    room_number && (where.name = { [Op.substring]: room_number })
    block_number && (where['$BlockNumber.name$'] = { [Op.substring]: block_number })
    area_name && (where['$Area.name$'] = { [Op.substring]: area_name })
    AreaId && (where['$Area.id$'] = AreaId)
    const { rows, count } = await RoomNumber.findAndCountAll({
        attributes: [[sequelize.col('RoomNumber.name'), 'room_number'], [sequelize.col('BlockNumber.name'), 'block_number'],
        [sequelize.col('Area.name'), 'area_name'], [sequelize.col('RoomNumber.id'), 'id']],
        where,
        include: [{ model: BlockNumber, attributes: [] },
        { model: Area, attributes: [] }],
        distinct: true,
        limit: limit * 1,
        offset: (page_index - 1) * limit
    })
    throw new Success({ list: rows, total: count })
}])

//删除
router.set('/delete', [auth('deleteArea'), async (ctx) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const type = v.get('query.type')
    if (type == 1) {
        const count = await User.count({ where: { BlockNumberId: id } })
        if (count) throw new Forbbidend('当前地域存在账号')
        await BlockNumber.destroy({
            where: {
                id
            }
        })
    } else if (type == 2) {
        const count = await User.count({ where: { AreaId: id } })
        if (count) throw new Forbbidend('当前地域存在账号')
        await Area.destroy({
            where: {
                id
            }
        })
    } else {
        const count = await User.count({ where: { RoomNumberId: id } })
        if (count) throw new Forbbidend('当前地域存在账号')
        await RoomNumber.destroy({
            where: {
                id
            }
        })
    }
    throw new Success('删除成功')
}])

export { router }